<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>Document</title>
    <style>
        
    </style>
</head>
<body>
    
</body>
<script>

    // 自定义事件系统
    // 绑定：绑定发布和订阅的关系
    // 触发：发布者发布信息
    // 删除：将订阅者和发布者的关系解除绑定


    function myEvent(){
        // 记录自定义的事件类型和对应的事件处理函数
        this.msg = {};
        // 将自定义的事件类型和指定的事件处理函数绑定
        this.add = function(type, cb){
            // 判断是否已经存在该自定义事件类型
            if(this.msg[type]){
                // 存在，增加一个新事件处理函数
                this.msg[type].push(cb);
            }else{
                // 不存在，直接设置一个数组，内放置本次的事件处理函数
                this.msg[type] = [cb];
            }
        }
        // 将自定义的事件类型和指定的事件处理函数解绑
        this.remove = function(type, cb){
            // 先判断是否存在该自定义事件类型，不存在，结束
            if(!this.msg[type]) return;
            // 从该自定义事件类型的事件处理函数中找到当前要删除的事件处理函数
            const idx = this.msg[type].indexOf(cb)
            if(idx !== -1){
                // 删除
                this.msg[type].splice(idx, 1);
            }
        }
        // 用于触发指定的自定义事件类型
        this.emit = function(type){
            // 先判断是否存在该自定义事件类型，不存在，结束
            if(!this.msg[type]) return;
            // 遍历该自定义事件类型的事件处理函数并依此执行
            this.msg[type].forEach(val=>{
                val();
            })
        }
    }


    const e = new myEvent();

    // 绑定
    e.add("abc", f1);
    e.add("abc", f3);
    e.add("abc", f4);
    e.add("qwe", f2);
    e.add("qwe", f1);
    e.add("asd", f4);

    // 删除
    e.remove("abc", f1);
    e.remove("qwe", f3);
    e.remove("zxc", f3);

    // 发布
    e.emit("abc");  // 3, 4
    e.emit("qwe");  // 2, 1
    e.emit("asd");  // 4



    function f1(){
        console.log(1);
    }
    function f2(){
        console.log(2);
    }
    function f3(){
        console.log(3);
    }
    function f4(){
        console.log(4);
    }

    
</script>
</html>